package org.apache.shenyu.plugin.cryptor.strategy;

import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import java.security.Security;

public class SM4Strategy implements CryptorStrategy {

    private static final Logger LOG = LoggerFactory.getLogger(SM4Strategy.class);

    static {
        // 注册 Bouncy Castle 提供的加密算法
        Security.addProvider(new BouncyCastleProvider());
    }

    private static final String ALGORITHM = "SM4/ECB/PKCS7Padding"; // SM4算法

    private static final String CHARSET = "UTF-8";

    private static final String SM4 = "SM4";

    @Override
    public String decrypt(String key, byte[] encryptData) throws Exception {
        Cipher cipher = Cipher.getInstance(ALGORITHM);
        SecretKeySpec keySpec = new SecretKeySpec(key.getBytes(CHARSET), SM4);
        cipher.init(Cipher.DECRYPT_MODE, keySpec);
        byte[] decryptedData = cipher.doFinal(hexToBytes(new String(encryptData)));
        return new String(decryptedData, CHARSET);
    }

    @Override
    public String encrypt(String key, String data) throws Exception {
        Cipher cipher = Cipher.getInstance(ALGORITHM);
        SecretKeySpec keySpec = new SecretKeySpec(key.getBytes(CHARSET), SM4);
        cipher.init(Cipher.ENCRYPT_MODE, keySpec);
        byte[] encryptedData = cipher.doFinal(data.getBytes(CHARSET));
        return bytesToHex(encryptedData);
    }

    // 辅助方法：将字节数组转换为十六进制字符串
    private String bytesToHex(byte[] bytes) {
        StringBuilder sb = new StringBuilder();
        for (byte b : bytes) {
            sb.append(String.format("%02x", b));
        }
        return sb.toString();
    }

    // 将十六进制字符串转换为字节数组
    private byte[] hexToBytes(String hex) {
        int length = hex.length();
        byte[] bytes = new byte[length / 2];
        for (int i = 0; i < length; i += 2) {
            bytes[i / 2] = (byte) ((Character.digit(hex.charAt(i), 16) << 4)
                    + Character.digit(hex.charAt(i + 1), 16));
        }
        return bytes;
    }
}
